# -*- coding:utf-8 -*-
# author:qiong   time:2020/5/27
import time

from PIL import Image
from os import listdir
from natsort import natsorted
import numpy as np
import os
import re
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
Image.MAX_IMAGE_PIXELS = 2300000000

class sort_numbers():
    def sort_key(self,s):  # 指定字符串中第一个数字来排序
        # 排序关键字匹配
        # 匹配开头数字序号
        if s:
            try:
                c = re.findall('\d+', s)[0]
            except:
                c = -1
            return int(c)

    def strsort(self,alist):

        alist.sort(key=self.sort_key)
        return alist

Sort_Numbers_in_string = sort_numbers()

def visible_box(img, white=220, ratio=0.99):
    """
    获取图像的可视区域
    :param img: PIL.Image.Image，目标图像
    :param white: 白色像素灰度阀值
    :param ratio: 白色像素比例阀值
    :return: 可视区域，4元素元组
    """

    first_col, first_row = 0, 0
    last_col, last_row = width, height = img.size

    # print(img.convert('L'))
    # print(np.asarray(img.convert('L')))
    white_arr = np.where(np.asarray(img.convert('L')) > white, 1, 0)

    # 从上往下，按行推进
    global n
    start = 0
    flag = True

    while flag ==True:
        for i, row in enumerate(white_arr[start:],start):
            print(i,sum(row),sum(row) / width )

            if sum(row) / width < ratio:        # 判断到不是纯白区域 ，不是纯白区域就进入后面程序  纯白是1，纯黑是0
                # print(i)
                start = i           # 记录彩色区域高度
                for k, row in enumerate(white_arr[start:],start):       #从不是纯白区域开始往下继续判断直到达到纯白区域
                    if sum(row) / width == 1:
                        start = k
                        end = k
                        for z, row in enumerate(white_arr[end:], end):      # 从纯白区域开始直到不是纯白区域
                            if sum(row) / width < ratio:
                                if z == height-1:
                                    flag = False
                                    last_row = height

                                    if (last_row == height and first_row == 0 and last_row - first_row > 4000) or (last_row == height and last_row - first_row > 4000):
                                        visible_box1(first_col, first_row, last_col, last_row)
                                        break

                                    box = first_col, first_row, last_col, last_row
                                    save_path(box)
                                    break
                                else:       # 判断白色区域有多长，截取中间
                                    if z - first_row < 1500:
                                        break
                                    else:
                                        if height - z < 500:
                                            break
                                        else:
                                            white_middle = int((z - k) / 2)
                                            last_row = white_middle + end

                                            if last_row - first_row > 4000:
                                                # visible_box1(first_col, first_row, last_col, last_row)
                                                start = visible_box1(first_col, first_row, last_col, last_row)[3]
                                                first_row = start
                                                break

                                            box = first_col, first_row, last_col, last_row
                                            save_path(box)
                                            first_row = last_row
                                            break
                            elif z == height-1:
                                flag = False
                                last_row = height

                                if (last_row == height and first_row == 0 and last_row - first_row > 4000) or (last_row == height and last_row - first_row > 4000) or (last_row - first_row > 4000):
                                    visible_box1(first_col, first_row, last_col, last_row)
                                    break

                                box = first_col, first_row, last_col, last_row
                                save_path(box)
                                break
                        break
                    elif k == height-1:     # 直到最后一像素没有白色
                        flag = False
                        last_row = height

                        if (last_row == height and first_row == 0 and last_row - first_row > 4000) or (last_row == height and last_row - first_row > 4000):
                            visible_box1(first_col, first_row, last_col, last_row)
                            break

                        box = first_col, first_row, last_col, last_row
                        save_path(box)
                        break
                break
            elif i == height - 1:  # 直到最后一像素没有白色
                flag = False
                last_row = height

                if (last_row == height and first_row == 0 and last_row - first_row > 4000) or (last_row == height and last_row - first_row > 4000):
                    visible_box1(first_col, first_row, last_col, last_row)
                    break

                box = first_col, first_row, last_col, last_row
                save_path(box)
                break



    return first_col, first_row, last_col, last_row     # 左 上 右 下


def visible_box1(first_col, first_row, last_col, last_row, black=30, ratio=0.01):
    """
    获取图像的可视区域
    :param img: PIL.Image.Image，目标图像
    :param black: 黑色像素灰度阀值
    :param ratio: 黑色像素比例阀值
    :return: 可视区域，4元素元组
    """

    # first_col, first_row = 0, 0
    # last_col, last_row = width, height = img.size
    width, height = last_col, last_row

    # print(img.convert('L'))
    # print(np.asarray(img.convert('L')))
    black_arr = np.where(np.asarray(img.convert('L')) > black, 1, 0)
    L_value = np.asarray(img.convert('L'))
    # 从上往下，按行推进
    global n
    start = 0
    flag = True
    while flag ==True:
        for i, row in enumerate(black_arr[start:],start):
            # print(i,sum(row),sum(row) / width)

            # if sum(row) / width > ratio:        # 判断到不是纯黑区域 ，不是纯黑区域就进入后面程序  纯白是1，纯黑是0
                # print(i)
            if list(black_arr[i]).count(0) / len(black_arr[i]) > 0.90 or max(L_value[i]) - min(L_value[i]) < 35:
                last_row = i
                start = i

                if i == height - 1:  # 直到最后一像素没有白色
                    flag = False
                    last_row = height
                    box = first_col, first_row, last_col, last_row
                    print(box)
                    save_path(box)
                    first_row = last_row
                    break
                elif last_row - first_row < 1000:
                    continue
                elif height -last_row < 500:
                    flag = False
                    last_row = height
                    box = first_col, first_row, last_col, last_row
                    print(box)
                    save_path(box)
                    break
                # flag = False
                else:
                    box = first_col, first_row, last_col, last_row
                    print(box)
                    save_path(box)
                    first_row = last_row
                    break
            elif i == height - 1:  # 直到最后一像素没有白色
                flag = False
                last_row = height
                box = first_col, first_row, last_col, last_row
                save_path(box)
                break




    return first_col, first_row, last_col, last_row     # 左 上 右 下



def save_path(cbox):
    global n
    global chapter_name
    region = img.crop(cbox)
    n = n + 1
    copy_path = os.path.join(copy_file,chapter_name, '%s.jpg' % n)
    copy_chapter_path = os.path.join(copy_file,chapter_name)
    if not os.path.exists(copy_chapter_path):
        os.makedirs(copy_chapter_path)
    if os.path.exists(copy_chapter_path):

        region.save(copy_path)


# 图片拼接



n = 0


# 多话数切图
file_basepath = r'input_pic'  # --------- 需要修改的基础文件夹
lit= os.listdir(file_basepath)   # 装入首文件下下面所有文件夹和文件到列表里
lit = Sort_Numbers_in_string.strsort(lit)   # 对文件夹按数字排序

copy_file = r'test_out'     # ---- 剪切导出文件夹


# 宽度不统一的提示，并跳过切图
dir_li =[]
del_l =[]
first_width = 0
for i in lit:
    t = 0
    title_path = os.path.join(file_basepath, i)
    pic = os.listdir(title_path)
    for m in pic:
        t += 1
        pic_path = os.path.join(title_path, m)
        # print(pic_path)
        img = Image.open(pic_path)
        # print(img.size)
        img_size = img.size
        # print(img_size[1])
        width = int(img_size[0])   #宽度
        # print(width)
        # 记录第一张图的宽度
        if t == 1:
            first_width = width
            continue
        else:
            pass

        if width == int(first_width):   # 宽度与第一张图是否一致
            pass
        else:
            # problem_pic = os.path.basename(os.path.dirname(pic_path))
            problem_pic = os.path.dirname(pic_path)
            print(problem_pic)
            del_l.append(i)
            break

# 宽度不统一文件夹写入文档
with open('width_disunity.txt', 'w', encoding='utf-8') as f:
    f.write('宽度不一致'+str(del_l))

# 跳过宽度不统一的文件夹
for d in del_l:
    lit.remove(d)

# print(lit)


# 所有图片合成一张图
def pic_compound(cut_pictures):

    lit_pic = listdir(cut_pictures)
    lit_pic = natsorted(lit_pic)
    ims = [Image.open(cut_pictures + '\\' + fn) for fn in lit_pic if fn.endswith(".jpg")]  # 打开路径下的所有图片
    width, height = ims[0].size  # 获取拼接图片的宽和高
    all_height = 0
    for hh in ims:
        all_height += hh.size[1]
    # print(ims)
    result = Image.new(ims[0].mode, (width, all_height))    # 获得新图长宽
    box_h = 0
    for j, im in enumerate(ims):        # 拼接到新图的位置
        result.paste(im, box=(0, box_h))
        box_h += im.size[1]
        print(j)
    return result


for chapter in lit:
    comic_chapter = os.path.join(file_basepath,chapter)
    # pic_lit = os.listdir(comic_chapter)
    # pic_lit = Sort_Numbers_in_string.strsort(pic_lit)
    chapter_name = chapter
    img = pic_compound(comic_chapter)


    if img.mode == "P":
        img = img.convert('RGB')

    try:
        visible_box(img)
        n = 0
    except Exception as e:
        with open('wrong.txt','a',encoding='utf-8') as g:
            g.write(time.asctime()+str(e))
